<?php

/** Dataxi login control functions
 *
 *  This code is licensed under GPL2.
 *  See LICENSE or www.gnu.org for more details.
 *
 *  @author Henri Ranki & Jyry Kuukkanen
 *
 *  $Id: dzlogin.php 595 2006-04-03 16:00:47Z jyry $
 */


include_once("solisttable.php");
include_once("sostring.php");
include_once("sostreams.php");
include_once("soset.php");
include_once("dzconst.php");
include_once("dzgeneric.php");
include_once("dzuser.php");
include_once("dzsesam.php");
include_once("dzlang.php");
include_once("dzmanager.php");
include_once("dzerror.php");


/** Return codes */
define(DZ_LOGIN_ERROR, 0);              /* An error occurred. */
define(DZ_LOGIN_SEND_LOGIN_SCREEN, 1);  /* Show login screen, user rejected */
define(DZ_LOGIN_OK, 2);                 /* User ok and has a session. */
define(DZ_LOGIN_SEND_SESSION_LIST, 3);  /* User ok, but sessions open. Send
                                           list of sessions for the user */
define(DZ_LOGIN_SEND_FRAMESET, 4);      /* Send the frameset used by Dataxi */

/** Dataxi login states */
define(DZ_LOGIN_STATE_START, 0);             /* First time connection */
define(DZ_LOGIN_STATE_VERIFY_USER, 1);       /* Verify the user and password */
define(DZ_LOGIN_STATE_GET_SESSIONS, 2);      /* Get the users open sessions */
define(DZ_LOGIN_STATE_SHOW_SESSION_LIST, 3); /* Open session listing */
define(DZ_LOGIN_STATE_SESSION_SELECTED, 4);  /* Open old session */
define(DZ_LOGIN_STATE_NEW_SESSION, 5);       /* Start new section */
define(DZ_LOGIN_STATE_LOGIN_OK, 6);          /* User & session verified */
define(DZ_LOGIN_STATE_DELETE_SESSION, 7);    /* Delete the selected session */

/** Sessions list buttons */
define(DZ_SESSION_OPEN_BTN, 1);              /** Open existing session */
define(DZ_SESSION_DELETE_BTN, 2);            /** Delete existing session */


/** A data structure that is used to return the result to Jarva.
 *  @var int $Status The result of login (DZ_LOGIN_SEND_FRAMESET etc.)
 *  @var string $Screen The next view shown to the user if needed
 *  @var int $Session The session choosen by user or new session id, that was
 *      created
 */
class dzLoginResult {
    var $Status;
    var $Screen;
    var $Session;
}; // dzLoginResult


/** Wrapper to get login sys msg
 *  @return Returns a system msg/title/caption used in login process.
 */
function dzLoginMsg($MsgID, $Lang) {
  return dzGetSysMsg(basename(__FILE__), $MsgID, $Lang);
}; // dzLoginMsg


/** Get the possible languages from dzlang.ini
 *  @return soSet Languages (code as key, name as value)
 */
function getLanguages() {
    $ini_stream = "file://".dzGetDataxiPath()."/dzlang.ini";

    $result = new soSet();
    $ini = new soIni($ini_stream);

    $key = 0;
    $keycount = $ini->getValueCount(DZIS_SYS);
    for ($key = 0; $key < $keycount; $key++) {
        $title = $ini->getValue(DZIS_SYS, $key, SOINI_NOSUB);
        if (!$ini->getError()) {
            $result->setItem($ini->getValueName(DZIS_SYS, $key), $title);
        } // if !$iniFile->getError()
    }; // for

    return $result;
}; // getLanguages


/** Finds out the session ID according to session index
 *  Asks the session ID from Kone. Sends the session index to kone.
 *  @param int $Index Session index
 *  @param string $Username Session owner
 *  @return string Session ID or -1 on error
 */
function getSessionID($Index, $Username) {
    $itu = new dzItu();
    
    /* Set request type, user and session */
    $itu->setBlockItem(DZI_CONTROL, DZK_REQUEST, DZK_REQ_OPEN_SES);
    $itu->setBlockItem(DZI_CONTROL, DZK_USER, $Username);
    $itu->setBlockItem(DZI_CONTROL, DZK_SESSION_INDEX, $Index);

    /* Send request */
    $result_itu = sendRpcToKone($itu);

    /* Check for rpc error */
    if (isRpcError($result_itu)) {
        $result = -1;
    } else {
        $rpc_result = $result_itu->getBlockItemAt(DZI_CONTROL, DZK_RESULT);
        if ($rpc_result != DZR_OK) {
            $result = -1;
        } else {
            $result = $result_itu->getBlockItemAt(DZI_CONTROL, DZK_SESSION_ID);
        } // if $session
    } // if (isRpcError($result_itu))

    return $result;
} // getSessionID


/** Returns list of available login screen languages for a TR element
 *  @return string TD's for a TR of languages available.
 */
function getLangList($MainScript) {
    $lang_set = getLanguages();
    $keys = $lang_set->getKeys();
    foreach ($keys as $key) {
        $result .= "<TD><A HREF='$MainScript?FramesOk=yes&dzLanguage=$key'>".
                   $lang_set->getitem($key)."</A><TD>\n";
    }; // foreach

    return $result;
}; // getLangList


/** Displays a screen to prompt for username and password
 *  @param string $Lang Language code
 *  @param string $Msg Optional message to display before prompts.
 *  @return string Login screen HTML code
 */
function dzMakeLoginScreen($Lang, $Msg = "") {
    $path = dzGetDataxiPath()."/".DZIS_DIALOGS;
    $result = soFileToString($path."/".
              soExtractVal(basename(__FILE__), ".", 1).".html");
    $mainscript = dzGetMainScriptName();

    $site_inc = dzGetIniPath(DZID_SITE_INC_FOLDER);

    if ($Msg) {
        $error_color = dzGetIniItem(DZCL_SECTION, DZCL_ERROR_WARNING, "app");
        $Msg = "<TR><TD COLSPAN=2>$Msg</TD></TR>";
    };
    $result = str_replace(soAddQuotes("msg", SO_DOLLAR), $Msg, $result);
    $result = str_replace(soAddQuotes("language", SO_DOLLAR), $Lang, $result);
    $result = str_replace(soAddQuotes("mainscript", SO_DOLLAR),
                          $mainscript, $result);
    $result = str_replace(soAddQuotes("state", SO_DOLLAR),
                          DZ_LOGIN_STATE_VERIFY_USER, $result);
    $result = str_replace(soAddQuotes("userid", SO_DOLLAR),
                          dzLoginMsg("username", $Lang), $result);
    $result = str_replace(soAddQuotes("password", SO_DOLLAR),
                          dzLoginMsg("password", $Lang), $result);
    $result = str_replace(soAddQuotes("langlist", SO_DOLLAR),
                          getLangList($mainscript), $result);
    $result = str_replace(soAddQuotes("bgcolor", SO_DOLLAR),
                          $bg_color, $result);
    $result = str_replace(soAddQuotes("title", SO_DOLLAR),
                          dzLoginMsg("title", $Lang), $result);
    $result = str_replace(soAddQuotes("stylesheet", SO_DOLLAR),
                          $site_inc."/".DZCSS_DEFAULT.".css", $result);
    return $result;
}; // dzMakeLoginScreen()


/** Display a list of open sessions for the user
 *  @param string $User Username
 *  @param string $Passwd User's password
 *  @param array/string $SesList List of sessions
 *  @param string $lang Language code
 *  @param bool $MaxSessions Max session count for this user.
 */
function dzMakeSessionList($User, $Passwd, $SesList, $Lang) {
    $Lang = strtolower($Lang);
    $mainscript = dzGetMainScriptName();
    $ses_count = count($SesList);

    /* request user info */
    $itu = new dzItu();
    $itu->setBlockItem(DZI_CONTROL, DZK_REQUEST, DZK_REQ_USER_INFO);
    $itu->setBlockItem(DZI_CONTROL, DZK_USER, $User);
    $result_itu = sendRpcToKone($itu);
    $max_sessions = $result_itu->getBlockItemAt(DZI_CONTROL, DZU_MAXSESSIONS);

    $site_inc = dzGetIniPath(DZID_SITE_INC_FOLDER);

    $title = str_replace("%1", "'".$User."'",
                 dzLoginMsg("open_sessions_title", $Lang));
    $result = "<HTML><HEAD><TITLE>".$title."</TITLE>".
        "<link rel=stylesheet href=".$site_inc."/".DZCSS_DEFAULT.".css>".
        "</HEAD>\n".
        "<BODY><FORM METHOD=post ACTION=".$mainscript."?FramesOk=yes&".
        DZRI_LANGUAGE."=".$Lang.">\n".
        "<INPUT TYPE=HIDDEN NAME='".DZRI_USER."' VALUE='".$User."'>\n".
        "<INPUT TYPE=HIDDEN NAME='".DZRI_PASSWD."' VALUE='".$Passwd."'>\n".
        "<INPUT TYPE=HIDDEN NAME='".DZRI_STATE."' VALUE='".
        DZ_LOGIN_STATE_SESSION_SELECTED."'>\n";

    $list = new soListTable();
    $list->Centered = true;
    $owner = dzLoginMsg("owner", $Lang);
    $started = dzLoginMsg("started", $Lang);
    $start_title = dzLoginMsg("start_title", $Lang);
    $delete_title = dzLoginMsg("delete_title", $Lang);
    $open_sessions_title = dzLoginMsg("open_sessions_title", $Lang);

    $bg_color = dzGetIniItem(DZCL_SECTION, DZCL_HEADER_BG, "app");
    $list->setTitles("$owner;$started;*$start_title;*$delete_title");
    /* Two buttons per row. Start session and delete session */
    $list->setWidgets(array(SO_LIST_TABLE_BUTTON, SO_LIST_TABLE_BUTTON),
                      array("", "  X  "));

    $result .= "<CENTER><TABLE><TR><TD><TR>\n".
               "<td><h3>".$title."</h3></td</tr><tr><td>\n";

    for ($c = 0; $c < $ses_count; $c++) $list->addRow($SesList[$c]);

    $result .= $list->make();
    $result .= "<TD></TR>\n";

    if (!$max_sessions || ($max_sessions > $ses_count)) {
        $msg = dzLoginMsg("start_new_session", $Lang);
        $result .= "<TR><TD colspan=4 align=center>".
                   "<INPUT TYPE=SUBMIT NAME='listTable'".
                   " VALUE='".$msg."'></TD></TR>\n";
    }; // if
    $result .= "</TABLE></CENTER>\n";

    $result .= "</FORM></BODY></HTML>\n";

    return $result;
} // dzMakeSessionList()


/** Actual login process
 *  This is a state machine that controls the login process.
 *  @param ? $VarSet
 *  @param string $Lang Language code
 *  @param bool SendFrames ?
 */
function dzLogin($VarSet, $Lang, $SendFrames = false) {
    include_once("sodebug.php");

    /* Create the result data structure, that contains the information how to
       proceed when we exit the login state machine (in Jarva) */
    if ($SendFrames) {
        $result = new dzLoginResult();
        $result->Status = DZ_LOGIN_SEND_FRAMESET;
        $result->Screen = dzMakeFrameSet();
        return $result;
    };

    /* Find out the current state */
    if ($VarSet->itemExists(DZRI_STATE)) {
        $state = $VarSet->getItem(DZRI_STATE);
    } else {
        $state = DZ_LOGIN_STATE_START;
    }; // else if

    if ($_SERVER["PHP_AUTH_USER"]) {
        $username = $_SERVER["PHP_AUTH_USER"];
        $password = $_SERVER["PHP_AUTH_PW"];
        if ($state == DZ_LOGIN_STATE_START) {
            $state = DZ_LOGIN_STATE_VERIFY_USER;
        }; // if
    } else {
        $username = $VarSet->getItem(DZRI_USER);
        $password = $VarSet->getItem(DZRI_PASSWD);
    }; // if
    if (trim($password)) $password = md5(trim($password));

    /* Get the pressed button and the index of selected session */
    $button = intval(soExtractVal($VarSet->getItem("soListResult"), "_", 1));
    $session = intval(soExtractVal($VarSet->getItem("soListResult"), "_", 2));
    $msg = "";

    /* Enter in the state machine that takes care of the login process */
    for (;;) {
        switch ($state) {
            case DZ_LOGIN_STATE_START:
                /* Start the login process.
                   Show the login screen for the user */
                soDebug("dzLogin/start: DZ_LOGIN_STATE_START", SOD_LO);

                $result = new dzLoginResult();
                $result->Status = DZ_LOGIN_SEND_LOGIN_SCREEN;
                $result->Screen = dzMakeLoginScreen($Lang, $msg);
                return $result; // <-- EXIT
                break;

            case DZ_LOGIN_STATE_VERIFY_USER:
                soDebug("dzLogin: DZ_LOGIN_STATE_VERIFY_USER", SOD_LO);

                /* Create request Itu */
                $itu = new dzItu();
                /* set request type */
                $itu->setBlockItem(DZI_CONTROL, DZK_REQUEST,
                                   DZK_REQ_CHECK_USER);

                /* Set user information */
                $itu->setBlockItem(DZI_CONTROL, DZK_USER,
                                   $username);
                $itu->setBlockItem(DZI_CONTROL, DZK_PASSWORD,
                                   $password);

                /* Send result to Itu */
                $result_itu = sendRpcToKone($itu);

                /* check for rpc error */
                if (isRpcError($result_itu)) {
                    $fault_string = getRpcErrorText($result_itu);
                    $msg = dzLoginMsg("Rpc failed:".$fault_string, $Lang);
                    $state = DZ_LOGIN_STATE_START;
                    continue;
                } // if (isRpcError($result_itu))

                $result = $result_itu->getBlockItemAt(DZI_CONTROL, DZK_RESULT);
                switch ($result) {
                    case DZVU_UNKNOWN_USER:
                    case DZVU_CHECK_FAILED:
                        /* Error loging in. Start from beginning */
                        $msg = dzLoginMsg("unknown_user", $Lang);
                        $state = DZ_LOGIN_STATE_START;
                        break;

                    default:
                        /* User ok */
                        $state = DZ_LOGIN_STATE_GET_SESSIONS;
                } // switch ($result)
                break;

            case DZ_LOGIN_STATE_GET_SESSIONS:
                soDebug("dzLogin: DZ_LOGIN_STATE_GET_SESSIONS", SOD_LO);
                /* Create request Itu */
                $itu = new dzItu();
                /* set request type */
                $itu->setBlockItem(DZI_CONTROL, DZK_REQUEST, DZK_REQ_SES_LIST);
                /* Set user information */
                $itu->setBlockItem(DZI_CONTROL, DZK_USER, $username);
                $itu->setBlockItem(DZI_CONTROL, DZK_INFO, DZK_LANG);
                /* Send result to Itu */
                $result_itu = sendRpcToKone($itu);
                /* check for rpc error */
                if (isRpcError($result_itu)) {
                    $fault_string = getRpcErrorText($result_itu);
                    $msg = dzLoginMsg("Rpc failed:".$fault_string, $Lang);
                    $state = DZ_LOGIN_STATE_START;
                    continue;
                } // if (isRpcError($result_itu))

                /* Users language definition overrides current language */
                $users_lang = $result_itu->getBlockItemAt(DZI_CONTROL,
                                                          DZK_LANG);
                if ($users_lang) $Lang = $users_lang;

                $ses_count = $result_itu->getBlockItemAt(DZI_CONTROL,
                                                         DZK_RESULT);
                if ($ses_count == 0) {
                    /* No existing session. So start a new one. */
                    $state = DZ_LOGIN_STATE_NEW_SESSION;
                } else {
                    soDebug("dzLogin: The user got ".$ses_count.
                            " open sessions", SOD_LO);
                    $state = DZ_LOGIN_STATE_SHOW_SESSION_LIST;
                } // if $ses_count
                break;

            case DZ_LOGIN_STATE_SHOW_SESSION_LIST:
                soDebug("dzLogin: DZ_LOGIN_STATE_SHOW_SESSION_LIST", SOD_LO);
                /* The user has open sessions we'll return the user a list
                   of existing sessions. From that list the user can choose
                   one or create a new session. The list is stored in table
                   called $UserSes. It was set in state
                   DZ_LOGIN_STATE_GET_SESSIONS */
                $ses_list = $result_itu->getBlockItem(DZI_CONTROL,
                                                      DZK_SESSION_LIST);

                $result = new dzLoginResult();
                $result->Screen = dzMakeSessionList($username,
                                                    $password,
                                                    $ses_list,
                                                    $Lang);
                $result->Status = DZ_LOGIN_SEND_SESSION_LIST;

                return $result; // <-- EXIT
                break;

            case DZ_LOGIN_STATE_SESSION_SELECTED:
                soDebug("dzLogin: DZ_LOGIN_STATE_SESSION_SELECTED", SOD_LO);

                if ($button == DZ_SESSION_DELETE_BTN) {
                    $state = DZ_LOGIN_STATE_DELETE_SESSION;
                    continue;  //  <-- continue
                } // if $button

                /* Is an old session were choosen login is ok. Otherwise
                   create a new session */
                if ($session != 0) {
                    /* We know session index but not the session id. We must
                       ask that from Kone. That is done with open_session
                       request.

                       Set the index of the session. *note* the indez
                       is one based */
                    $result = getSessionID($session-1, $username);
                    /* check for rpc error */
                    if ($result == -1) {
                        $fault_string = getRpcErrorText($result_itu);
                        $msg = dzLoginMsg("Rpc failed:".$fault_string, $Lang);
                        $state = DZ_LOGIN_STATE_START;
                        continue;
                    } else {
                        $session = $result;
                        $state = DZ_LOGIN_STATE_LOGIN_OK;
                    } // if $result
                } else {
                    $state = DZ_LOGIN_STATE_NEW_SESSION;
                }
                break;

            case DZ_LOGIN_STATE_NEW_SESSION:
                soDebug("dzLogin: DZ_LOGIN_STATE_NEW_SESSION", SOD_LO);

                /* Create request Itu */
                $itu = new dzItu();
                /* set request type */
                $itu->setBlockItem(DZI_CONTROL, DZK_REQUEST, DZK_REQ_OPEN_SES);
                /* Set session index to -1. This is create a new session id */
                $itu->setBlockItem(DZI_CONTROL, DZK_SESSION_INDEX, -1);
                /* Set user information */
                $itu->setBlockItem(DZI_CONTROL, DZK_USER, $username);
                /* Send result to Itu */
                $result_itu = sendRpcToKone($itu);
                /* check for rpc error */
                if (isRpcError($result_itu)) {
                    $fault_string = getRpcErrorText($result_itu);
                    $msg = dzLoginMsg("Rpc failed:".$fault_string, $Lang);
                    $state = DZ_LOGIN_STATE_START;
                    continue;
                } // if (isRpcError($result_itu))
                $result = $result_itu->getBlockItemAt(DZI_CONTROL, DZK_RESULT);
                if ($result != DZR_OK) {
                    /* Some hacker coming in? Let's go back to
                      login screen! */
                    $msg = "Sorry! No hacking is allowed!";
                    $state = DZ_LOGIN_STATE_START;
                } // if
                $session = $result_itu->getBlockItemAt(DZI_CONTROL,
                                                       DZK_SESSION_ID);
                $state = DZ_LOGIN_STATE_LOGIN_OK;

                break;

            case DZ_LOGIN_STATE_LOGIN_OK:
                soDebug("dzLogin: DZ_LOGIN_STATE_LOGIN_OK", SOD_LO);

                /* Store the session Id and the owner to system file */
                addSessionToFile($session, $username);
                $result = new dzLoginResult();
                $result->Session = $session;
                $result->Status = DZ_LOGIN_OK;
                return $result; // <-- EXIT
                break;

            case DZ_LOGIN_STATE_DELETE_SESSION:
                soDebug("dzLogin: DZ_LOGIN_STATE_DELETE_SESSION", SOD_LO);
                /* We know session index but not the session id. We must
                   ask that from Kone. That is done with open_session
                   request

                   Set the index of the session. *note* the indez
                   is one based */
                $id = getSessionID($session-1, $username);

                /* Remove all the cache files that belong to this session */
                dzManRemoveSessionFile($id);

                /* Now delete session*/
                /* Remove session from the session base. Send close_session
                request to Kone */
                $itu = new dzItu();
                /* set request type */
                $itu->setBlockItem(DZI_CONTROL, DZK_REQUEST,
                                   DZK_REQ_CLOSE_SES);
                /* Set user information */
                $itu->setBlockItem(DZI_CONTROL, DZK_USER, $username);
                $itu->setBlockItem(DZI_CONTROL, DZK_SESSION, $id);
                /* Send result to Itu */
                $result_itu = sendRpcToKone($itu);
                /* check for rpc error */
                if (isRpcError($result_itu)) {
                    $fault_string = getRpcErrorText($result_itu);
                    $msg = dzLoginMsg("Rpc failed:".$fault_string, $Lang);
                    $state = DZ_LOGIN_STATE_START;
                    continue;
                } // if (isRpcError($result_itu))

                $state = DZ_LOGIN_STATE_GET_SESSIONS;
                break;

            default:
                /* this is an error state. Execution should never come here */
               $msg = "Somethig strange happened. You should never see this ".
                       "message!<BR>";
               $state = DZ_LOGIN_STATE_START;
        } // switch ($State)
    } // for (;;)
}; // dzLogin


/** Gets main script and relative site tmp paths.
 *  N.B. Does not return anything, both params are passed by reference.
 *  @var string $MainScriptPath Main script path (under host name, if any)
 *  @var string $SiteTmpPath Site tmp path under MainScriptPath
 */
function getSitePaths(&$MainScriptPath, &$SiteTmpPath) {
    /* Sort out the route back to main script from site tmp */
    $SiteTmpPath = dzGetIniItem(DZIS_FOLDERS, DZID_SITE_TMP_FOLDER, "site");
    if (!$SiteTmpPath) $SiteTmpPath = "~";

    if (soStrPos($SiteTmpPath, "~") < 0) {
        dzSysError("Site tmp path should be relative ".
                   "(Not '$SiteTmpPath')<br>".
                   "e.g. ~/tmp define site_tmp in site.ini's folders section ",
                   DZSE_INSTALL, true);
    } else {
        /* Create the relative path back to main script from the site tmp
         * folder */
        $scount = soStrCount($SiteTmpPath, "/");
        for ($c = 0; $c < $scount; $c++) $MainScriptPath .= "../";

        $url_path = dirname($_SERVER["SCRIPT_NAME"]);
        if ($url_path == "/") $url_path = "";

        /* Remove the tilde. It is not allowed in the url string and add the
         * url path */
        $SiteTmpPath = $url_path.soSwapStr($SiteTmpPath, "~", "", 1);
    }; // if

}; // getSitePaths


/** Copies necessary dataxi files to site tmp folder
 *  @return bool True on success or false on error.
 */
function dzSetupSiteFiles() {

    $site_tmp_path = dzGetIniPath(DZID_SITE_TMP_FOLDER);
    getSitePaths($main_script_path, $rel_site_tmp_path);
    $dialog_path = dzGetDataxiPath()."/".DZIS_DIALOGS;

    /* Dummy space file "paavo" */
    $paavo = "file://".$site_tmp_path."/".PAAVO_HTML;
    $outstream = &new soOutputStream($paavo,
                                     "<HTML></HTML>\n");
    if ($outstream->Error) {
        dzSysError("Could not write '".$paavo."' to '$site_tmp_path'!".
                   "<br>Try to change the write permission of the ".
                   "application directory.",
                DZSE_INSTALL, true);
        return 0; // <-- EXIT
    }; // if

    /* Frame holder file */
    $frameset = soFileToString($dialog_path."/".FRAMES_HTML);
    $title = dzGetIniItem(DZIS_GENERAL, "appname", "site");
    $frameset = str_replace(soAddQuotes("title", SO_DOLLAR),
                            $title, $frameset);
    $frameset = str_replace(soAddQuotes("path", SO_DOLLAR),
                            $rel_site_tmp_path, $frameset);
    $frameset = str_replace(soAddQuotes("mainscript_path", SO_DOLLAR),
                            $main_script_path, $frameset);
    $frameset = str_replace(soAddQuotes("mainscript", SO_DOLLAR),
                            dzGetMainScriptName(), $frameset);
    $outstream = &new soOutputStream("file://".$site_tmp_path."/".FRAMES_HTML,
                                     $frameset);
    if ($outstream->Error) {
        dzSysError("Could not write file://".FRAMES_HTML." to application ".
                "dir!<br>Try to change the write permission of the ".
                "application directory.", true);
        return 0; // <-- EXIT
    }; // if

    return 1;
}; // dzSetupSiteFiles



/** Build the html frameset to be sent to client and the script that closes
 *  the browser window and open a new one for Dataxi
 *  @return string Frame HTML code
 */
function dzMakeFrameSet() {
    $url_path = dirname($_SERVER["SCRIPT_NAME"]);
    if ($url_path == "/") $url_path = "";

    /* If any site file missing, copy them */
    $paavo = "$site_tmp_path/".PAAVO_HTML;
    $dzFramesFile = "$site_tmp_path/".FRAMES_HTML;
    if ((!file_exists($paavo)) ||
        (!file_exists($dzFramesFile))) dzSetupSiteFiles($site_tmp_path);

    /* Is the status bar shown? Defaults to no */
    $show_statusbar = dzGetIniItem(DZIS_GENERAL, "show_statusbar",
                                   "site", "bool");
    if ($show_statusbar) {
        $show_statusbar = "";
    } else {
        $show_statusbar = "menubar=no,hotkeys=no,location=no,".
                          "toolbar=no,statusbar=no";
    }; // else if

    /* Find out should we open an new window for Dataxi. Default is yes. */
    $open_new_window = soGetBoolValue(dzGetIniItem(DZIS_GENERAL,
                                                   DZID_OPEN_WINDOW));

    /* Create the name for the window that is opened for Dataxi. The timestamp
       is included to get different names. Otherwise only one window is opened
       all the time. */
    getSitePaths($main_script_path, $rel_site_tmp_path);

    $window_name = "dzWindow".time();
    $result = "<HTML><HEAD><SCRIPT language='JavaScript'><!--\n";
    if ($open_new_window) {
        $result .= "NewWnd = window.open('$rel_site_tmp_path/".FRAMES_HTML.
                   "', '$window_name', '$show_statusbar');\n";
    } else {
        $result .= "location='".$rel_site_tmp_path."/".FRAMES_HTML."';\n";
    } // if

    /* Close yourself
       It seems there is an annoying security js feature here: a confirmation
       dialog box is shown if this page was not the only one in the windows
       history list */
    if ($open_new_window) $result .= "NewWnd.focus();\n";
    $close_launch_window =
        dzGetIniItem(DZIS_GENERAL, DZID_CLOSE_LAUNCHER, "site");
    if (($close_launch_window)) $result .= "self.close();\n";
    $result .= "//--></SCRIPT></HEAD>\n";

    return $result;
}; // dzMakeFrameSet


/** Adds a session to sessions file.
 *  Sessions file has the list of sessions and the session owners .
 *  @param string $SessionId The session id to store
 *  @param string $Owner The session owner's user name
 *  @return bool True if ok, otherwise false
 */
function addSessionToFile($SessionId, $Owner) {
    $tmp_path = dzGetIniPath(DZID_CACHE_FOLDER);
    $session_file = "file://".soJoinStr($tmp_path, "/", DZ_SESSION_FILE);

    /* Read in the current session list */
    $ini_file = new soInputStream($session_file);

    /* If file already existed take the old sessions out of it. */
    if (!$ini_file->Error) {
        $sessions = unserialize($ini_file->Data);
    } else {
        $sessions = new soSet();
    }; // if

    /* Add the current session to to list */
    $sessions->setItem(md5($SessionId), $Owner);

    /* Write modified list on the disk.*/
    $result = writeSessionFile($sessions);
    if (!$result) {
        dzSysError("Check the tmp directory path in site.ini. ".
                   "Dataxi could not write there!");
    }; // if

    return $result;
} // addSessionToFile


/** Deletes a session from sessions file.
 *  The sessions file has the list of sessions and the session owners .
 *  @param string $SessionId The session id to delete
 *  @return bool   true if ok, otherwise false
 */
function delSessionFromFile($SessionId) {
    $tmp_path = dzGetIniPath(DZID_CACHE_FOLDER);
    $session_file = "file://".soJoinStr($tmp_path, "/", DZ_SESSION_FILE);

    /* Read in the current session list */
    $ini_file = new soInputStream($session_file);

    /* If file already existed take the old sessions out of it. */
    if (!$ini_file->Error) {
        $sessions = unserialize($ini_file->Data);

        /* Del the current session from the list */
        if ($sessions->delItem(md5($SessionId))) {
            $result = writeSessionFile($sessions);
        } else {
            $result = false;
        } // if
    } else {
        $result = false;
    }; // if

    return $result;
} // delSessionFromFile


/** Checks if the user with specified session id exists.
 *  @param string $SessionId The session id
 *  @param string $Owner The session owner's user name
 *  @return bool True if ok, otherwise false
 */
function querySessionFromFile($SessionId, $Owner) {
    $tmp_path = dzGetIniPath(DZID_CACHE_FOLDER);
    $session_file = "file://".soJoinStr($tmp_path, "/", DZ_SESSION_FILE);

    $ini_file = new soInputStream($session_file);

    /* If file already existed take the old sessions out of it. */
    if (!$ini_file->Error) {
        $sessions = unserialize($ini_file->Data);
        /* Add the current session to to list */
        $real_owner = $sessions->getItem(md5($SessionId));

        if ((!$sessions->Error) && ($real_owner == $Owner)) {
            $result = true;
        } else {
            $result = false;
        }; // else if
    } else {
        $result = false;
    }; // else if

    return $result;
} // querySessionFromFile


/** Writes the session list to file. Uses locking.
 *  @param soSet $sessionList List of sessions and owner
 *  @return bool True if ok, otherwise false
 */
function writeSessionFile($SessionList) {
    $tmp_path = dzGetIniPath(DZID_CACHE_FOLDER);

    $session_file = "file://".soJoinStr($tmp_path, "/", DZ_SESSION_FILE);
    $lock_file = soJoinStr($tmp_path, "/", DZ_SESSION_LOCK_FILE);

    /* Open lock file */
     if (!$fp = fopen($lock_file,'w+')) {
        /* Lock file open failed */
        $result = false;
     } else {
        /* Lock file. Block while waiting wor the lock to free. */
        $operation = LOCK_EX;
        $wait = TRUE;
        flock ($fp, $operation, $block);

        /* Got the lock -> Write modified list on the disk.*/
        $out_file = &new soOutputStream($session_file, 
                                        serialize($SessionList));
        flock($fp, LOCK_UN);
        fclose($fp);
        $result = !$out_file->Error;
     } // fp = fopen

    return $result;
} // writeSessionFile

?>
